#!/usr/bin/env python2
#-*- coding: utf-8 -*-

import commands
import os
import sys
import socket
import time
import copy
import json
import errno
import random
import getopt

# admin_path = os.path.abspath(os.path.split(os.path.realpath(__file__))[0])
# sys.path.insert(0, "%s/../" % (admin_path))

from buddha.lichbd import Lichbd

from utils import Exp, _dmsg, _dwarn, _derror, _exec_pipe1


def usage(unhide = False):
    print ("usage:")
    print (sys.argv[0] + " df [-f json]")
    print (sys.argv[0] + " mon_status")
    print (sys.argv[0] + " osd lspools")
    print (sys.argv[0] + " osd pool create {<uuid>} {<int[0-]>}")
    print (sys.argv[0] + " osd pool delete <pool-name> {<pool-name>} {--yes-i-really-really-mean-it}")
    print (sys.argv[0] + " -f json auth get-or-create client.zstack mon 'allow r' osd 'allow *'")

def _stats():
    '''
    {"total_bytes":259579871232,"total_used_bytes":121509847040,"total_avail_bytes":124813299712}
    '''
    stats = {}
    total = 0
    total_used = 0

    cmd = ["/opt/fusionstack/lich/bin/lich", "stat"]
    #cmd = ["/opt/fusionstack/lich/bin/lich.cluster", "stat"]
    try:
        out,err = _exec_pipe1(cmd, 0, False)
    except Exp as e:
        raise Exp(e.errno, e.err)

    for line in out.splitlines():
        if "capacity:" in line:
            total = line.split(':')[-1]
        elif "used:" in line:
            total_used = line.split(':')[-1]

    stats["total_bytes"] = int(total)
    stats["total_used_bytes"] = int(total_used)
    stats["total_avail_bytes"] = stats["total_bytes"] - stats["total_used_bytes"]

    return stats


def _pool_info(name):
    info = {}
    cmd = ["/opt/fusionstack/lich/libexec/lichbd", "info", name]
    try:
        out,err = _exec_pipe1(cmd, 0, False)
    except Exp as e:
        return info

    for l in out.splitlines():
        if "Id:" in l:
            Id = l.split('.')[-2]
            info["id"] = Id
        elif "Size:" in l:
            stats = {}
            stats["max_avail"] = int(l.split()[1])
            stats["bytes_used"] = random.randint(0, stats["max_avail"])
            stats["kb_used"] = stats["bytes_used"] / 1024
            stats["objects"] = stats["kb_used"] / 1024
            info["stats"] = stats

    return info


def _pools():
    '''
    [{"name":"rbd","id":0,"stats":{"kb_used":0,"bytes_used":0,"max_avail":41603885864,"objects":0}},
    {"name":"cephfs_data","id":1,"stats":{"kb_used":0,"bytes_used":0,"max_avail":41603885864,"objects":0}},
    {"name":"cephfs_metadata","id":2,"stats":{"kb_used":3,"bytes_used":2068,"max_avail":41603885864,"objects":20}}]
    '''

    # cmd = ['/opt/fusionstack/lich/libexec/lichbd', 'pool', 'ls', '-p', 'iscsi']
    # try:
    #     out,err = _exec_pipe1(cmd, 0, False)
    # except Exp as e:
    #     raise Exp(e.errno, e.err)

    lichbd = Lichbd()
    out = lichbd.list_all_pools()

    pools = []
    for line in out.splitlines():
        pool = {}
        name = line.strip().split()[-1]
        pool["name"] = name

        info = _pool_info(name)
        Id = 0
        if "id" in info:
            Id = info["id"]
        pool['id'] = Id

        if "stats" in info:
            pool["stats"] = info["stats"]

        pools.append(pool)

    return pools


def df(is_json = 0):
    res = {}

    res["stats"] = _stats()
    res["pools"] = _pools()

    return res

def mon_status():
    '''
    res = '{\
    "name":"c",\
    "rank":2,\
    "state":"peon",\
    "election_epoch":74,\
    "quorum":[0,1,2],\
    "outside_quorum":[],\
    "extra_probe_peers":[],\
    "sync_provider":[],\
    "monmap":\
        {"epoch":1,\
        "fsid":"a5ccb3d8-6c30-4c55-89bb-fe0fc34c45a5",\
        "modified":"2016-04-22 16:47:06.304214",\
        "created":"2016-04-22 16:47:06.304214",\
        "mons":\
            [{"rank":0,"name":"a","addr":"192.168.120.31:6789\/0"},\
            {"rank":1,"name":"b","addr":"192.168.120.31:6790\/0"},\
            {"rank":2,"name":"c","addr":"192.168.120.31:6791\/0"}]\
        }\
    }'
    '''

    res = '{"name":"c","rank":2,"state":"peon","election_epoch":74,"quorum":[0,1,2],"outside_quorum":[],"extra_probe_peers":[],"sync_provider":[],"monmap":{"epoch":1,"fsid":"a5ccb3d8-6c30-4c55-89bb-fe0fc34c45a5","modified":"2016-04-22 16:47:06.304214","created":"2016-04-22 16:47:06.304214","mons":[{"rank":0,"name":"a","addr":"192.168.120.31:6789\/0"},{"rank":1,"name":"b","addr":"192.168.120.31:6790\/0"},{"rank":2,"name":"c","addr":"192.168.120.31:6791\/0"}]}}'

    return res.strip()

def lspools():
    '''
    0 rbd,1 cephfs_data,2 cephfs_metadata,
    '''
    res = ""
    pools = _pools()
    for pool in pools:
        res += str(pool['id']) + ' ' + pool['name'] + ','
    return res


def create(name):
    if not name:
        _derror("need poolname")

    lichbd = Lichbd()
    lichbd.pool_create(name)

    _dmsg("pool '%s' created"%name)


def delete(name):
    if not name:
        _derror("need poolname")

    lichbd = Lichbd()
    lichbd.pool_rm(name)

    _dmsg("pool '%s' removed" % name)


def auth(ext):
    '''
    -f json auth get-or-create client.zstack mon 'allow r' osd 'allow *'
    [{"entity":"client.zstack","key":"AQBQJRpXx7P6ARAAVoDS8N31GsDojeNajRInQQ==","caps":{"mon":"allow r","osd":"allow *"}}]
    ['get-or-create', 'client.zstack', 'mon', 'allow r', 'osd', 'allow *']
    '''
    res = {}
    res["entity"] = ext[1]
    res['key'] = "AQBQJRpXx7P6ARAAVoDS8N31GsDojeNajRInQQ==" 
    caps = {}
    caps[ext[2]] = ext[3]
    caps[ext[4]] = ext[5]
    res['caps'] = caps

    return [res]

def main():
    module = ['osd']
    submodule = ['pool']
    commands = ['json', 'human-readable', 'df', 'mon_status', 'create', 'delete', 'lspools', 'auth']

    unhide = False
    arg_osd = False
    arg_pool = False
    argv = []

    argv = sys.argv[1:]
    if argv[0] in module:
        argv = argv[1:]
        if argv[0] in submodule:
            argv = argv[1:]

    for i in range(len(argv)):
        if argv[i] in commands:
            argv[i] = '--' + argv[i]

    try:
        opts, args = getopt.getopt(
            argv,
            'hf',
            ['json', 'human-readable', 'df', 'mon_status', 'create=', 'delete=', 'lspools', 'auth']
            )
    except getopt.GetoptError, err:
        print str(err)
        usage(unhide)
        exit(errno.EINVAL)

    op = ""
    ext = None
    host = None
    is_json = 0
    readable = 0
    formats = ""
    
    newopts = copy.copy(opts)
    for o, a in opts:
        if o in ('--json'):
            is_json = 1
            newopts.remove((o, a))
        elif o in ('-h', '--human-readable'): 
            readable = 1
            newopts.remove((o, a))
        elif o in ('-f', '--format'): 
            newopts.remove((o, a))

    for o, a in newopts:
        if o in ('--df'):
            res = df(is_json)
            if is_json:
                print json.dumps(res)
            else:
                print json.dumps(res, sort_keys=False, indent=4)

        elif o in ('--mon_status'):
            res = mon_status()
            print res

        elif o in ('--lspools'):
            res = lspools()
            print res

        elif o in ('--create'):
            create(a)

        elif o in ('--delete'):
            delete(a)

        elif o in ('--auth'):
            ext = args
            res = auth(ext)
            if is_json:
                print json.dumps(res)
            else:
                print json.dumps(res, sort_keys=False, indent=4)


if __name__ == "__main__":
    if len(sys.argv) == 1:
        usage()
    else:
        main()
